本次目標
預設上,需要裝 Metrics-server 來進行 CPU/Memory 監控。
$ helm --kubeconfig ~/.kube/infrlab upgrade --install metrics-server --version 3.12.1 metrics-server/metrics-server --create-namespace -n monitor
在 K3d 環境中會自動安裝。
HPA(HorizontalPodAutoscaler)用於自動更新負載資源,會針對 Deployment
、StatefulSet
等資源。目的是自動縮長工作負載以滿足需求。對於 DaemonSet
資源是無法使用 HPA。
HPA 是屬於水平擴展,與 VPA 垂直擴展不同。VPA 是針對於記憶體或 CPU 並對當前運行的 Pod 進行擴展。
資源決定了 HPA 控制器的行為,會定期調整其目標(Deployment)的所需規模,以符合觀察到的指標,例如:平均 CPU 使用率、平均記憶體使用率或任何其他指定的自訂指標。同時 HPA 添加了縮放速率配置參數,以控制縮放速率。
HPA 是一個迴圈實現,由 kube-controller-manager
的 --horizontal-pod-autoscaler-sync-period
參數設定,預設 15s。
每段時間內,控制管理器(control management) 會依據 HPA 定義中指定的指標獲取資源使用率。控制管理器找 scaleTargetRef
定義的資源目標,並關聯其 Pod,並從 Metric API 針對每個 Pod 的資源指標或自訂指標取得指標 API。
定義好的 HorizontalPodAutoscaler
資源如下:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
annotations:
app.quarkus.io/quarkus-version: 3.9.4
app.quarkus.io/commit-id: 260a13c09b391a4a1edb357fb2d305523cfbf9d5
app.quarkus.io/vcs-uri: https://github.com/CCH0124/O11y-with-quarkus.git
app.quarkus.io/build-timestamp: 2024-04-27 - 10:36:18 +0000
labels:
app.kubernetes.io/name: quarkus-hpa
app.kubernetes.io/version: 1.0.0-SNAPSHOT
app.kubernetes.io/managed-by: quarkus
name: quarkus-hpa
namespace: itachi
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: quarkus-hpa
minReplicas: 1
maxReplicas: 25
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 200
policies:
- type: Pods
value: 2
periodSeconds: 60
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Pods
value: 2
periodSeconds: 60
- type: Percent
value: 40
periodSeconds: 60
HorizontalPodAutoscaler
資源scaleTargetRef
綁定某資源,下面為 DeploymentHorizontalPodAutoscaler.spec.metrics
欄位是用於觸發副本數量的規範,而副本數透過將目標值(HorizontalPodAutoscaler.spec.metrics.type.resource.target)與當前值之間的比率乘以當前 Pod 數量來計算,官方的演算定義如下desiredReplicas = ceil[currentReplicas * ( currentMetricValue / desiredMetricValue )]
而 HorizontalPodAutoscaler.spec.metrics.type
能夠定義不同的指標類型像是 ContainerResource
、External
、Object
、Pods
或 Resource
,來滿足不同需求可能是流量等。如果沒有設置,則預設指標將設定為 80% 的平均 CPU 使用率。本文章實驗範例是使用 Resource
。
Resource
指標是指 Kubernetes Pod 的 CPU 和記憶體使用率與 Pod 規範的限制和請求中提供的值相比。Kubernetes 透過 Metric Server 獲取這些指標。在將這些值與目標值進行比較之前,會先將這些值平均。也就是說,如果應用程式正在運行三個副本,則將計算利用率值的平均值,並將其與部署規範中定義的 CPU 和記憶體請求進行比較。HorizontalPodAutoscaler.spec.metrics.resource
(ResourceMetricSource) 是指 Kubernetes 已知的資源指標像是請求和限制中指定的資源指標,並描述當前擴縮目標(HorizontalPodAutoscaler.spec.metrics.type.resource.target
) 例如 CPU 或記憶體然後針對每個 Pod。
ResourceMetricSource
指示如何根據請求和限制中指定的 Kubernetes 已知資源指標進行擴縮容,同時描述目前擴展目標中每個 Pod 的 CPU/Memory。在與目標值比較之前,這些指標值將會被平均。
在實驗所提供的 HPA 範例檔案,有定義了 behavior
字段。其讓縮放行為可被調整或用來穩定縮放過程。這將單一擴展行為策略或多個擴展行為策略附加到 HPA,並且會自動選擇導致給定實例的最大更改量的策略。
...
behavior:
scaleDown:
stabilizationWindowSeconds: 200
policies:
- type: Pods
value: 2
periodSeconds: 60
- type: Percent
value: 10
periodSeconds: 60
periodSeconds
以上面範例來看,表示 HPA 每 60 秒會計算一次期望副本(desiredReplicas)數。
略過 stabilizationWindowSeconds
配置,上述的範例提供兩個策略。如果有 100 個副本正在運行,HPA 將查看兩個可用的策略。第一個策略是自動縮放在 60 秒內一次刪除 2 個 Pod;第二個策略是自動縮放器在 60 秒內刪除目前副本數量的 $10%$。而第二個策略影響最大,因為它將在前 60 秒的移動窗口刪除 10 個 Pod。因此剩下 $100-10$ 個 Pod。在接下來的 60 秒移動窗口中,將從剩餘 90 個 Pod 中刪除 $900.1 = 9$ 個 Pod,剩下 81 個 Pod。接著 60 秒移動窗口,$81 - ceil(810.1) = 72$。當副本達到 20 個時,第一個策略將接管,因為第二個策略的影響會比 2 個 Pod 的影響要小。因此,從 20 個 Pod 開始,自動縮放器將在每次迭代中不斷刪除 2 個 Pod。對於 Policy
是指當下可以最多縮容或擴展 Pod 數量,並非是要設定的值。
stabilizationWindowSeconds
用於透過觀察指定時間段的歷史資料來限制縮放決策。這有助於防止 HPA 在短時間內做出多個縮減決策,從而導致副本數反覆上下波動。假設指標顯示目標應該縮小時,演算法會查看先前計算的所需狀態,並使用指定間隔中的最高值。在演示範例中,將考慮過去 200 秒的所有所需狀態。這近似於滾動最大值,並避免縮放演算法頻繁刪除 Pod,只是為了稍後觸發重新建立等效的 Pod。以上面的範例,表示 HPA 在決定縮減 Pod 數量之前,會考慮過去 200 秒内計算出的最高期望副本數。
當 stabilizationWindowSeconds
為 0,則表示不應延遲,應立即改變副本的數量。
在縮容時,應該在最後一個 stableWindowSeconds
期間選擇最安全且最大的期望副本數量;在擴容時,應該在最後一個 stableWindowSeconds
期間選擇最安全且最小的期望副本數量。這可以參考原始碼。
根據上述的範例,兩者如何協同工作防止 Pod 數量抖動?
periodSeconds
,來根據當前資源計算出期望值stabilizationWindowSeconds
(範例中為 200 秒) 內計算出的所有期望副本數,並選擇其中最高的那個值作為縮減依據另一方面 behavior
配置目標縮放行為,分別為 scaleUp
和 scaleDown
欄位。如果未設置,則使用預設的 HPAScalingRules
進行縮放。預設行為如下配置
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
對於 scaleDown
,穩定視窗(stabilizationWindowSeconds) 為 300 秒或 --horizontal-pod-autoscaler-downscale-stabilization
標誌的值。scaleDown
的策略只有一個,該策略允許刪除 $100%$ 目前正在運行的副本,這表示著可以縮小到允許的最小副本。對於 scaleUp
來說,沒有穩定視窗,值為 0。當指標顯示目標應該擴大時,目標會立即擴大。scaleUp
有 2 個策略,分別是每 15 秒增加 4 個 Pod 或 100% 擴大目前正在運行的副本,直到 HPA 達到穩定狀態。
selectPolicy
字段則是選擇策略中影響最大或最小數量 Pod 的策略。其也可以是 disable
。如果未設置,則使用預設值 Max
。
behavior:
scaleUp:
policies:
- type: Percent
value: 200
periodSeconds: 30
200,表示以 2 被方式增長。如果應用程式以 1 個 Pod 啟動,它透過以下數量 Pod 進行擴展,並快速擴展至符合當下場景的數量
1 -> 3 -> 9 -> 27
behavior:
scaleUp:
policies:
- type: Percent
value: 200
periodSeconds: 60
scaleDown:
policies:
- type: Pods
value: 1
periodSeconds: 600
behavior:
scaleDown:
selectPolicy: Disabled
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 5
periodSeconds: 60
假設當前副本為 10 且 HPA 控制器每分鐘循環一次:
[10, 9, 8, 9]
[10, 9, 8, 9, 8]
。當中最大的值是 10
。因此它不會改變副本的數量。[9, 8, 9, 8, 7]
並刪除第一個推薦數據以保持相同視窗數量的推薦數據。此演算法選擇最大值 9 並將副本數量變更從 10 變成 9下個章節會實際使用 Quarkus 服務進行演示。